package br.edu.ifrn.potigol.lang;

import br.edu.ifrn.potigol.lang.Context;
import br.edu.ifrn.potigol.lang.Evaluable;
import br.edu.ifrn.potigol.lang.PotigolClass;
import br.edu.ifrn.potigol.lang.PotigolException;
import br.edu.ifrn.potigol.lang.PotigolObject;

/**
 * Manipula a captura da exceção.
 */
public class ExceptionHandler {
  private Evaluable handler;
  private String localName;
  private PotigolClass klass;
  
  /**
   * Cria um ExceptionHandler especializado em lidar com um tipo de exceção.
   * @param klass 		Classe runtime da exceção tratada.
   * @param localName 	Nome da variável local que a exceção será armazenada quando capturada.
   * @param handler 	Código para evaliação quando a exceção é capturada.
   */
  public ExceptionHandler(PotigolClass klass, String localName, Evaluable handler) {
    this.localName = localName;
    this.handler = handler;
    this.klass = klass;
  }
  
  /**
   * Retorna verdadeiro se o manipulador pode cuidar dessa exceção.
   */
  public boolean handle(PotigolException e) {
    return klass.isSubclass(e.getRuntimeClass());
  }
  
  /**
   * Chamado para executar um bloco catch quando ocorre uma exceção.
   */
  public PotigolObject run(Context context, PotigolException e) throws PotigolException {
    if (localName != null) {
      context.createLocal(localName, e.getRuntimeObject());
    }
    return handler.eval(context);
  }
}